import secrets
import json
import time
from web3 import Web3
from eth_account import Account

# 初始化Web3
w3 = Web3(Web3.HTTPProvider('https://bsc-dataseed.binance.org/'))
# w3 = Web3(Web3.HTTPProvider('https://data-seed-prebsc-1-s1.binance.org:8545'))

# 主钱包配置
MAIN_WALLET_PRIVATE_KEY = ''
MAIN_WALLET_ADDRESS = ''

def get_main_wallet_balance():
    """查询主钱包BNB余额"""
    balance = w3.eth.get_balance(MAIN_WALLET_ADDRESS)
    return w3.from_wei(balance, 'ether')
    
def get_token_balance(token_address, wallet_address):
    """查询指定代币余额"""
    try:
        contract = w3.eth.contract(address=token_address, abi=get_erc20_abi())
        balance = contract.functions.balanceOf(wallet_address).call()
        return w3.from_wei(balance, 'ether')
    except Exception as e:
        log(f"Error getting token balance for {wallet_address}: {str(e)}")
        return 0

# 合约地址

def log(message):
    print(message)
    try:
        from app import socketio
        socketio.emit('log_message', {'data': message})
    except:
        pass
# 正式
CAKE_TOKEN_ADDRESS = '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82'

# 测试
# CAKE_TOKEN_ADDRESS = "0xfa60d973f7642b748046464e165a65b7323b0dee"

CAKE_TOKEN_ADDRESS = Web3.to_checksum_address(CAKE_TOKEN_ADDRESS)
SYRUP_POOL_ADDRESS = '0x814D79E1f104dae6B7e482388Ecf8BFe28be8A84'
BGSC_TOKEN_ADDRESS = '0xa4B68D48D7bc6f04420e8077E6F74bdeF809dEa3'

# 默认gas设置
GAS_PRICE = w3.to_wei(0.1, 'gwei')
GAS_LIMIT = 300000
DECIMALS = 18
CHAINID = 56

# 1. 批量生成私钥和地址
def generate_wallets(n, output_file='wallets.txt'):
    wallets = []
    for _ in range(n):
        private_key = '0x' + secrets.token_hex(32)
        account = Account.from_key(private_key)
        wallets.append({
            'private_key': private_key,
            'address': account.address
        })
    
    with open(output_file, 'w') as f:
        json.dump(wallets, f, indent=4)
    return wallets

# 2. 批量转账BNB
def transfer_bnb(wallets, amount):
    main_account = Account.from_key(MAIN_WALLET_PRIVATE_KEY)
    nonce = w3.eth.get_transaction_count(MAIN_WALLET_ADDRESS)
    
    for wallet in wallets:
        tx = {
            'nonce': nonce,
            'to': wallet['address'],
            'value': w3.to_wei(amount, 'ether'),
            'gas': GAS_LIMIT,
            'gasPrice': GAS_PRICE,
            'chainId': CHAINID
        }
        
        signed_tx = main_account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully transferred {amount} BNB to {wallet['address']}")
        else:
            log(f"Failed to transfer BNB to {wallet['address']}")
        
        nonce += 1
        time.sleep(1)

# 3. 批量转账CAKE
def transfer_cake(wallets, amount):
    cake_contract = w3.eth.contract(address=CAKE_TOKEN_ADDRESS, abi=get_erc20_abi())
    main_account = Account.from_key(MAIN_WALLET_PRIVATE_KEY)
    nonce = w3.eth.get_transaction_count(MAIN_WALLET_ADDRESS)
    
    for wallet in wallets:
        tx = cake_contract.functions.transfer(
            wallet['address'],
            w3.to_wei(amount, 'ether')
        ).build_transaction({
            'chainId': CHAINID,
            'gas': GAS_LIMIT,
            'gasPrice': GAS_PRICE,
            'nonce': nonce
        })
        
        signed_tx = main_account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully transferred {amount} CAKE to {wallet['address']}")
        else:
            log(f"Failed to transfer CAKE to {wallet['address']}")
        
        nonce += 1
        time.sleep(1)

# 4. 批量授权糖浆池
def approve_syrup_pool(wallets):
    cake_contract = w3.eth.contract(address=CAKE_TOKEN_ADDRESS, abi=get_erc20_abi())
    
    for wallet in wallets:
        account = Account.from_key(wallet['private_key'])
        nonce = w3.eth.get_transaction_count(wallet['address'])
        
        tx = cake_contract.functions.approve(
            SYRUP_POOL_ADDRESS,
            2**256 - 1
        ).build_transaction({
            'chainId': CHAINID,
            'gas': GAS_LIMIT,
            'gasPrice': GAS_PRICE,
            'nonce': nonce
        })
        
        signed_tx = account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully approved SYRUP pool for {wallet['address']}")
        else:
            log(f"Failed to approve SYRUP pool for {wallet['address']}")
        
        time.sleep(1)

# 5. 批量质押CAKE
def stake_cake(wallets, amount):
    syrup_contract = w3.eth.contract(address=SYRUP_POOL_ADDRESS, abi=get_syrup_pool_abi())
    
    for wallet in wallets:
        account = Account.from_key(wallet['private_key'])
        nonce = w3.eth.get_transaction_count(wallet['address'])
        
        tx = syrup_contract.functions.deposit(
            w3.to_wei(amount, 'ether')
        ).build_transaction({
            'chainId': CHAINID,
            'gas': GAS_LIMIT,
            'gasPrice': GAS_PRICE,
            'nonce': nonce
        })
        
        signed_tx = account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully staked {amount} CAKE for {wallet['address']}")
        else:
            log(f"Failed to stake CAKE for {wallet['address']}")
        
        time.sleep(1)

# 6. 批量收割BGSC
def harvest_bgsc(wallets):
    syrup_contract = w3.eth.contract(address=SYRUP_POOL_ADDRESS, abi=get_syrup_pool_abi())
    
    for wallet in wallets:
        account = Account.from_key(wallet['private_key'])
        nonce = w3.eth.get_transaction_count(wallet['address'])
        
        tx = syrup_contract.functions.deposit(0).build_transaction({
            'chainId': CHAINID,
            'gas': GAS_LIMIT,
            'gasPrice': GAS_PRICE,
            'nonce': nonce
        })
        
        signed_tx = account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully harvested BGSC for {wallet['address']}")
        else:
            log(f"Failed to harvest BGSC for {wallet['address']}")
        
        time.sleep(1)

# 7. 批量取回质押
def unstake_cake(wallets, amount):
    syrup_contract = w3.eth.contract(address=SYRUP_POOL_ADDRESS, abi=get_syrup_pool_abi())
    
    for wallet in wallets:
        account = Account.from_key(wallet['private_key'])
        nonce = w3.eth.get_transaction_count(wallet['address'])
        
        tx = syrup_contract.functions.withdraw(
            w3.to_wei(amount, 'ether')
        ).build_transaction({
            'chainId': CHAINID,
            'gas': GAS_LIMIT,
            'gasPrice': GAS_PRICE,
            'nonce': nonce
        })
        
        signed_tx = account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully unstaked {amount} CAKE for {wallet['address']}")
        else:
            log(f"Failed to unstake CAKE for {wallet['address']}")
        
        time.sleep(1)

# 8. 批量发送CAKE回主钱包
def send_cake_to_main(wallets, amount):
    cake_contract = w3.eth.contract(address=CAKE_TOKEN_ADDRESS, abi=get_erc20_abi())
    
    for wallet in wallets:
        account = Account.from_key(wallet['private_key'])
        nonce = w3.eth.get_transaction_count(wallet['address'])
        
        # 获取钱包中的BGSC余额
        balance = cake_contract.functions.balanceOf(wallet['address']).call()
        log(f"{wallet['address']}: {balance}")
        
        if balance == 0:
            log(f"No CAKE balance in {wallet['address']}")
            continue
            
        tx = cake_contract.functions.transfer(
            MAIN_WALLET_ADDRESS,
            balance
        ).build_transaction({
            'chainId': CHAINID,
            'gas': GAS_LIMIT,
            'gasPrice': GAS_PRICE,
            'nonce': nonce
        })
        
        signed_tx = account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully sent all CAKE ({w3.from_wei(balance, 'ether')}) to main wallet from {wallet['address']}")
        else:
            log(f"Failed to send BGSC to main wallet from {wallet['address']}")
        
        time.sleep(1)

# 9. 批量发送BGSC回主钱包
def send_bgsc_to_main(wallets):
    bgsc_contract = w3.eth.contract(address=BGSC_TOKEN_ADDRESS, abi=get_erc20_abi())
    
    for wallet in wallets:
        account = Account.from_key(wallet['private_key'])
        nonce = w3.eth.get_transaction_count(wallet['address'])
        
        # 获取钱包中的BGSC余额
        balance = bgsc_contract.functions.balanceOf(wallet['address']).call()
        print(wallet['address'],":",balance)
        
        if balance == 0:
            log(f"No BGSC balance in {wallet['address']}")
            continue
            
        tx = bgsc_contract.functions.transfer(
            MAIN_WALLET_ADDRESS,
            balance
        ).build_transaction({
            'chainId': CHAINID,
            'gas': GAS_LIMIT,
            'gasPrice': GAS_PRICE,
            'nonce': nonce
        })
        
        signed_tx = account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully sent all BGSC ({w3.from_wei(balance, 'ether')}) to main wallet from {wallet['address']}")
        else:
            log(f"Failed to send BGSC to main wallet from {wallet['address']}")
        
        time.sleep(1)

# 10. 批量发送BNB回主钱包
def send_bnb_to_main(wallets):
    for wallet in wallets:
        account = Account.from_key(wallet['private_key'])
        nonce = w3.eth.get_transaction_count(wallet['address'])
        
        # 获取钱包中的BNB余额
        balance = w3.eth.get_balance(wallet['address'])
        #print(balance)
        #gas_cost = GAS_LIMIT * GAS_PRICE
        amount = balance - 2100000000000
        
        if amount < 0:
            log(f"Insufficient BNB balance in {wallet['address']} (balance: {w3.from_wei(balance, 'ether')} BNB)")
            continue
            
        tx = {
            'nonce': nonce,
            'to': MAIN_WALLET_ADDRESS,
            'value': amount,
            'gas': 21000,
            'gasPrice': GAS_PRICE,
            'chainId': CHAINID
        }
        
        signed_tx = account.sign_transaction(tx)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        
        if receipt.status == 1:
            log(f"Successfully sent {w3.from_wei(amount, 'ether')} BNB to main wallet from {wallet['address']}")
        else:
            log(f"Failed to send BNB to main wallet from {wallet['address']}")
        
        time.sleep(1)

def get_erc20_abi():
    return [{
        "inputs": [
            {"name": "_spender", "type": "address"},
            {"name": "_value", "type": "uint256"}
        ],
        "name": "approve",
        "outputs": [{"name": "", "type": "bool"}],
        "stateMutability": "nonpayable",
        "type": "function"
    }, {
        "inputs": [
            {"name": "_to", "type": "address"},
            {"name": "_value", "type": "uint256"}
        ],
        "name": "transfer",
        "outputs": [{"name": "", "type": "bool"}],
        "stateMutability": "nonpayable",
        "type": "function"
    }, {
        "inputs": [
            {"name": "_owner", "type": "address"}
        ],
        "name": "balanceOf",
        "outputs": [{"name": "", "type": "uint256"}],
        "stateMutability": "view",
        "type": "function"
    }, {
        "inputs": [],
        "name": "decimals",
        "outputs": [{"name": "", "type": "uint8"}],
        "stateMutability": "view",
        "type": "function"
    }, {
        "inputs": [],
        "name": "symbol",
        "outputs": [{"name": "", "type": "string"}],
        "stateMutability": "view",
        "type": "function"
    }, {
        "inputs": [],
        "name": "totalSupply",
        "outputs": [{"name": "", "type": "uint256"}],
        "stateMutability": "view",
        "type": "function"
    }]

def get_syrup_pool_abi():
    return [{
        "inputs": [
            {"name": "_amount", "type": "uint256"}
        ],
        "name": "deposit",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }, {
        "inputs": [
            {"name": "_amount", "type": "uint256"}
        ],
        "name": "withdraw",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }]

if __name__ == '__main__':
    # 示例用法
    # 生成钱包(只需运行一次)
    wallets = generate_wallets(10)
    
    # 从文件加载已生成的钱包
    with open('wallets.txt', 'r') as f:
        wallets = json.load(f)
    #给钱包转账bnb 0.001每个
    transfer_bnb(wallets, 0.001)

    #给钱包转账cake 100每个
    transfer_cake(wallets, 100)

    #授权钱包交互
    approve_syrup_pool(wallets)

    #质押cake
    stake_cake(wallets, 100)

    #收割bgsc
    harvest_bgsc(wallets)

    #解除质押cake
    unstake_cake(wallets, 100)

    #把cake从钱包转回主钱包
    send_cake_to_main(wallets, 100)

    把bgsc从钱包转回主钱包
    send_bgsc_to_main(wallets)

    #把bnb从钱包转回主钱包
    send_bnb_to_main(wallets)

    balance = get_main_wallet_balance()
    log(f"主钱包当前余额: {balance} BNB")
